<?php
class Alipay {
	private $gateway = "https://www.alipay.com/cooperate/gateway.do?"; //支付接口
	private $parameter; //全部需要传递的参数
	private $security_code; //安全校验码
	private $mysign; //签名
	private $partner; //合作伙伴ID
	private $sign_type; //加密方式 系统默认
	private $_input_charset; //字符编码格式
	private $transport; //访问模式
	

	public function getHtml($sOid, $sMoney, $sSubject, $sBody = null) {
		$parameter = array ();
		$parameter ['service'] = 'create_direct_pay_by_user';
		$parameter ['partner'] = Base::getConf ( 'alipay.partner' );
		if ($sReturn = $parameter ['return_url']) {
			$parameter ['return_url'] = $sReturn;
		}
		if ($sNotify = Base::getConf ( 'alipay.notify_url' )) {
			$parameter ['notify_url'] = $sNotify;
		}
		$parameter ['_input_charset'] = Base::getConf ( 'alipay.charset' );
		$parameter ['subject'] = $sSubject;
		$parameter ['body'] = $sBody;
		$parameter ['out_trade_no'] = $sOid;
		$parameter ['price'] = $sMoney;
		$parameter ['payment_type'] = '1';
		$parameter ['quantity'] = '1';
		$parameter ['logistics_fee'] = '0.00';
		$parameter ['logistics_payment'] = 'BUYER_PAY';
		$parameter ['logistics_type'] = 'EXPRESS';
		$parameter ['show_url'] = Base::getConf ( 'alipay.show_url' );
		$parameter ['seller_email'] = Base::getConf ( 'alipay.seller_email' );
		error_log ( var_export ( $parameter, true ) . "\n", 3, __DIR__ . '/alipay.log' );
		$this->alipayService ( $parameter, Base::getConf ( 'alipay.key' ) );
		return '<script>window.location="' . $this->createUrl () . '";</script>';
	}
	
	//构造支付宝外部服务接口控制
	public function alipayService($parameter, $security_code, $sign_type = "MD5", $transport = "http") {
		$this->parameter = $this->para_filter ( $parameter );
		$this->security_code = $security_code;
		$this->sign_type = $sign_type;
		$this->mysign = '';
		$this->transport = $transport;
		if ($parameter ['_input_charset'] == "")
			$this->parameter ['_input_charset'] = 'utf-8';
		if ($this->transport == "https") {
			$this->gateway = "https://www.alipay.com/cooperate/gateway.do?";
		} else
			$this->gateway = "http://www.alipay.com/cooperate/gateway.do?";
		$sort_array = array ();
		$arg = "";
		$sort_array = $this->arg_sort ( $this->parameter );
		while ( list ( $key, $val ) = each ( $sort_array ) ) {
			$arg .= $key . "=" . $this->charset_encode ( $val, $this->parameter ['_input_charset'] ) . "&";
		}
		$prestr = substr ( $arg, 0, count ( $arg ) - 2 ); //去掉最后一个问号
		$this->mysign = $this->sign ( $prestr . $this->security_code );
	}
	
	public function createUrl() {
		$url = $this->gateway;
		$sort_array = array ();
		$arg = "";
		$sort_array = $this->arg_sort ( $this->parameter );
		while ( list ( $key, $val ) = each ( $sort_array ) ) {
			$arg .= $key . "=" . urlencode ( $this->charset_encode ( $val, $this->parameter ['_input_charset'] ) ) . "&";
		}
		$url .= $arg . "sign=" . $this->mysign . "&sign_type=" . $this->sign_type;
		return $url;
	
	}
	
	public function arg_sort($array) {
		ksort ( $array );
		reset ( $array );
		return $array;
	
	}
	
	public function sign($prestr) {
		$mysign = "";
		if ($this->sign_type == 'MD5') {
			$mysign = md5 ( $prestr );
		} elseif ($this->sign_type == 'DSA') {
			//DSA 签名方法待后续开发
			die ( "DSA 签名方法待后续开发，请先使用MD5签名方式" );
		} else {
			die ( "支付宝暂不支持" . $this->sign_type . "类型的签名方式" );
		}
		return $mysign;
	
	}
	
	function para_filter($parameter) { //除去数组中的空值和签名模式
		$para = array ();
		while ( list ( $key, $val ) = each ( $parameter ) ) {
			if ($key == "sign" || $key == "sign_type" || $val == "")
				continue;
			else
				$para [$key] = $parameter [$key];
		}
		return $para;
	}
	
	//实现多种字符编码方式
	public function charset_encode($input, $_output_charset, $_input_charset = "utf-8") {
		$output = "";
		if (! isset ( $_output_charset ))
			$_output_charset = $this->parameter ['_input_charset'];
		if ($_input_charset == $_output_charset || $input == null) {
			$output = $input;
		} elseif (function_exists ( "mb_convert_encoding" )) {
			$output = mb_convert_encoding ( $input, $_output_charset, $_input_charset );
		} elseif (function_exists ( "iconv" )) {
			$output = iconv ( $_input_charset, $_output_charset, $input );
		} else
			die ( "sorry, you have no libs support for charset change." );
		return $output;
	}
	
	function alipayNotify($partner, $security_code, $sign_type = "MD5", $_input_charset = "utf-8", $transport = "http") {
		$this->partner = $partner;
		$this->security_code = $security_code;
		$this->sign_type = $sign_type;
		$this->mysign = "";
		$this->_input_charset = $_input_charset;
		$this->transport = $transport;
		if ($this->transport == "https") {
			$this->gateway = "https://www.alipay.com/cooperate/gateway.do?";
		} else
			$this->gateway = "http://notify.alipay.com/trade/notify_query.do?";
	
	}
	/****************************************对notify_url的认证*********************************/
	function notifyVerify() {
		if ($this->transport == "https") {
			$veryfy_url = $this->gateway . "service=notify_verify" . "&partner=" . $this->partner . "&notify_id=" . $_POST ["notify_id"];
		} else {
			$veryfy_url = $this->gateway . "partner=" . $this->partner . "&notify_id=" . $_POST ["notify_id"];
		}
		$veryfy_result = $this->get_verify ( $veryfy_url );
		$post = $this->para_filter ( $_POST );
		$sort_post = $this->arg_sort ( $post );
		while ( list ( $key, $val ) = each ( $sort_post ) ) {
			$arg .= $key . "=" . $val . "&";
		}
		$prestr = substr ( $arg, 0, count ( $arg ) - 2 ); //去掉最后一个&号
		$this->mysign = $this->sign ( $prestr . $this->security_code );
		if (eregi ( "true$", $veryfy_result ) && $this->mysign == $_POST ["sign"]) {
			return true;
		} else
			return false;
	}
	/*******************************************************************************************/
	
	/**********************************对return_url的认证***************************************/
	function returnVerify() {
		$sort_get = $this->arg_sort ( $_GET );
		while ( list ( $key, $val ) = each ( $sort_get ) ) {
			if ($key != "sign" && $key != "sign_type")
				$arg .= $key . "=" . $val . "&";
		}
		$prestr = substr ( $arg, 0, count ( $arg ) - 2 ); //去掉最后一个&号
		$this->mysign = $this->sign ( $prestr . $this->security_code );
		if ($this->mysign == $_GET ["sign"])
			return true;
		else
			return false;
	}
	/*******************************************************************************************/
	
	function get_verify($url, $time_out = "60") {
		$urlarr = parse_url ( $url );
		$errno = "";
		$errstr = "";
		$transports = "";
		if ($urlarr ["scheme"] == "https") {
			$transports = "ssl://";
			$urlarr ["port"] = "443";
		} else {
			$transports = "tcp://";
			$urlarr ["port"] = "80";
		}
		$fp = @fsockopen ( $transports . $urlarr ['host'], $urlarr ['port'], $errno, $errstr, $time_out );
		if (! $fp) {
			die ( "ERROR: $errno - $errstr<br />\n" );
		} else {
			fputs ( $fp, "POST " . $urlarr ["path"] . " HTTP/1.1\r\n" );
			fputs ( $fp, "Host: " . $urlarr ["host"] . "\r\n" );
			fputs ( $fp, "Content-type: application/x-www-form-urlencoded\r\n" );
			fputs ( $fp, "Content-length: " . strlen ( $urlarr ["query"] ) . "\r\n" );
			fputs ( $fp, "Connection: close\r\n\r\n" );
			fputs ( $fp, $urlarr ["query"] . "\r\n\r\n" );
			while ( ! feof ( $fp ) ) {
				$info [] = @fgets ( $fp, 1024 );
			}
			
			fclose ( $fp );
			$info = implode ( ",", $info );
			while ( list ( $key, $val ) = each ( $_POST ) ) {
				$arg .= $key . "=" . $val . "&";
			}
			
			return $info;
		}
	
	}
}